package com.springcloud.auth.modular.auth.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.net.NetUtil;
import com.alibaba.fastjson.JSON;
import com.springcloud.auth.config.OauthConfig;
import com.springcloud.auth.entity.TUserInfo;
import com.springcloud.auth.modular.auth.service.LoginService;
import com.springcloud.auth.param.LoginParam;
import com.springcloud.auth.service.TUserInfoService;
import com.springcloud.auth.utils.TokenUtil;
import com.springcloud.auth.vo.TokenVo;
import com.springcloud.commom.api.R;
import com.springcloud.commom.constant.SymbolConstant;
import com.springcloud.commom.utils.HttpServletUtil;
import com.springcloud.commom.utils.IpAddressUtil;
import com.springcloud.commom.utils.UUIDUtils;
import com.springcloud.commom.utils.UaUtil;
import com.springcloud.log.entity.SysVisLog;
import com.springcloud.log.enums.LogSuccessStatusEnum;
import com.springcloud.log.enums.VisLogTypeEnum;
import com.springcloud.log.feign.ILogClient;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.URLConnectionClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthResourceResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Date;
import java.util.Map;

@RestController
@RequestMapping("login")
@Validated
public class LoginController {

    @Resource
    private LoginService loginService;

    @Value("${server.port}")
    private String serverPort;

    @Resource
    private ILogClient logClient;

    @Resource
    private TUserInfoService userInfoService;

    @RequestMapping("login")
    public R login(@Valid LoginParam dto) throws Exception {
//        String code = redisUtil.get(StaticConfig.UserInfo.REDIS_CODE_LOGIN_KEY + dto.getCode());
//        if (StringUtils.isBlank(code)) {
//            return R.fail("验证码过期,请重新获取！");
//        }

        TUserInfo info = loginService.login(dto.getUserName(), dto.getPassword());

        //加入登录日志
        if (info != null) {
            // 获取token
            OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());

            String randomCode = UUIDUtils.createUUId();

            String baseUrl = "http://" + NetUtil.getLocalhostStr() + ":" + serverPort;

            String authUrl = baseUrl + OauthConfig.AUTH_URL + "?randomCode=" + randomCode;

            OAuthClientRequest userInfoRequest = new OAuthBearerClientRequest(authUrl).buildQueryMessage();

            OAuthResourceResponse resourceResponse = oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
            String entity = resourceResponse.getBody();

            TokenVo tokenVo = JSON.parseObject(entity, TokenVo.class);

            Map<String, Object> map = loginService.saveUserInfo(info, tokenVo);

            //登录完成，清楚验证码
//            redisUtil.del(StaticConfig.UserInfo.REDIS_CODE_LOGIN_KEY + dto.getCode());

            saveLoginLog(VisLogTypeEnum.LOGIN.getMessage(), info.getUserName(), LogSuccessStatusEnum.SUCCESS.getCode(), null);

            return R.data(map);
        } else {
            //登录失败
            saveLoginLog(VisLogTypeEnum.LOGIN.getMessage(), "", LogSuccessStatusEnum.FAIL.getCode(), "账号或密码错误!");
        }

        return R.fail("账号或密码错误!");
    }

    /**
     * 退出登录，清除accessTokon,refreshToken
     *
     * @return
     */
    @RequestMapping(value = "loginOut", method = RequestMethod.POST)
    public R loginOut() {
        loginService.loginOut();

        TUserInfo userInfo = TokenUtil.getUserInfo();

        TUserInfo selUserInfo =  userInfoService.getById(userInfo.getId());
        saveLoginLog(VisLogTypeEnum.EXIT.getMessage(), selUserInfo.getUserName(), LogSuccessStatusEnum.SUCCESS.getCode(), null);

        return R.success();
    }

    private void saveLoginLog(String name, String account, String successCode, String failMessage) {
        HttpServletRequest request = HttpServletUtil.getRequest();
        String ip = IpAddressUtil.getIp(request);
        String browser = UaUtil.getBrowser(request);
        String os = UaUtil.getOs(request);

        SysVisLog sysVisLog = new SysVisLog();

        sysVisLog.setName(name);
        sysVisLog.setIp(ip);
        sysVisLog.setBrowser(browser);
        sysVisLog.setOs(os);
        sysVisLog.setVisTime(new Date());
        sysVisLog.setAccount(account);
        sysVisLog.setLocation("");

        sysVisLog.setSuccess(successCode);

        sysVisLog.setVisType(VisLogTypeEnum.LOGIN.getCode());
        sysVisLog.setVisTime(DateTime.now());

        if (LogSuccessStatusEnum.SUCCESS.getCode().equals(successCode)) {
            sysVisLog.setMessage(VisLogTypeEnum.LOGIN.getMessage() + LogSuccessStatusEnum.SUCCESS.getMessage());
        }
        if (LogSuccessStatusEnum.FAIL.getCode().equals(successCode)) {
            sysVisLog.setMessage(VisLogTypeEnum.LOGIN.getMessage() +
                    LogSuccessStatusEnum.FAIL.getMessage() + SymbolConstant.COLON + failMessage);
        }

        logClient.saveVisLog(sysVisLog);
    }
}
